package com.yunsoft.gateway.interceptor.handler;

import com.fld.central.common.model.code.BaseCode;
import com.fld.central.common.model.exception.SpiException;
import com.fld.platform.commons.entity.auth.Credentials;
import com.fld.platform.commons.entity.auth.CredentialsHolder;
import com.fld.platform.redis.RedisMgrBean;
import com.yunsoft.gateway.interceptor.InterceptorAdapter;
import com.yunsoft.gateway.utils.RequestUtils;
import com.yunsoft.gateway.utils.SpringUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;

/**
 * 管理员授权拦截器
 * @author summerrains
 *
 */
public abstract class BaseHandlerInterceptor implements InterceptorAdapter {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(BaseHandlerInterceptor.class);
	
	private RedisMgrBean redisMgrBean;

	@Value("${jwt.secret}")
	private String secret ;

    /**
     * 获取redis
     * @return
     */
    protected RedisMgrBean getRedisMgrBean() throws SpiException {
    	if(redisMgrBean != null) {
    		return redisMgrBean;
    	}
    	redisMgrBean = SpringUtils.getBean(RedisMgrBean.class);
    	if(redisMgrBean == null) {
    		LOGGER.error("get redisMgrBean error,please import META-INF/applicationContext-redis.xml");
    		throw new SpiException(BaseCode.ERROR,"系统错误");
    	}
    	return redisMgrBean;
    }
    
    protected void checkAuthorization(HttpServletRequest request) throws SpiException {
		String jwt = RequestUtils.getJwt(request);

		if (StringUtils.isEmpty(jwt)) {
			throw new SpiException(BaseCode.JWT_NO_LOGIN,"未登录");
		} 
		
		Claims claims = null;
		try {
			claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(secret)).parseClaimsJws(jwt).getBody();
		} catch (ExpiredJwtException e) {
			LOGGER.error("JWT过期",e);
			throw new SpiException(BaseCode.JWT_EXPIRE,"TOKEN过期");
		} catch (UnsupportedJwtException e) {
			LOGGER.error("JWT不支持",e);
			throw new SpiException(BaseCode.JWT_UNSUPPORTED,"TOKEN错误");
		} catch (MalformedJwtException e) {
			LOGGER.error("JWT格式错误",e);
			throw new SpiException(BaseCode.JWT_UNSUPPORTED,"TOKEN错误");
		} catch (IllegalArgumentException e) {
			LOGGER.error("JWT参数错误",e);
			throw new SpiException(BaseCode.JWT_ARGUMENT_ERROR,"TOKEN错误");
		} catch (Exception e) {
			LOGGER.error("未知异常",e);
			throw new SpiException(BaseCode.JWT_NO_LOGIN,"未登录");
		}
		if (claims == null) {
			throw new SpiException(BaseCode.JWT_NO_LOGIN,"未登录");
		}
		Map<String, Object> map = null;

		if (map == null) {
			map = new HashMap<String, Object>();
			map.put("id", Long.parseLong(claims.getAudience()));
			map.put("username", claims.get("nickName",String.class));
			map.put("Authorization-Status", "normal");
			map.put("Authorization", jwt);
			map.put("status", claims.get("status",Integer.class));
			map.put("nickname", claims.getIssuer());
		}
		// 把用户信息放入全局变量中
		CredentialsHolder.set(Credentials.fromMap(map));
	}

	protected <A extends Annotation> A findAnnotation(HandlerMethod handlerMethod, Class<A> annotationClass) {
		//方法上的注解
		A annotation = handlerMethod.getMethod().getAnnotation(annotationClass);
		//查询类上的注解
		if(annotation == null) {
			//类上是否有注解
			Class clazz = handlerMethod.getMethod().getDeclaringClass();
			while (clazz != null) {
				annotation = (A) clazz.getDeclaredAnnotation(annotationClass);
				if(annotation != null) {
					break;
				}
				clazz = clazz.getSuperclass();
			}
		}
		return annotation;
	}
	
}
